perf: avoid Rc refcount overhead in DomSlot chain traversal#4088
perf: avoid Rc refcount overhead in DomSlot chain traversal#4088Madoshakalaka merged 4 commits intomasterfrom
Conversation
Traverse the DynamicDomSlot chain using raw pointers instead of Rc::clone/drop per hop. The chain is transitively kept alive by the borrowed &self, so raw pointer access is sound.
|
Visit the preview URL for this PR (updated for commit 75d1266): https://yew-rs-api--pr4088-perf-domslot-path-co-hkn87gb5.web.app (expires Sat, 25 Apr 2026 03:15:56 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 |
Benchmark - coreYew MasterPull Request |
Size ComparisonDetails
✅ None of the examples has changed their size significantly. |
Benchmark - SSRYew MasterDetails
Pull RequestDetails
|
|
benchmarks looking good 0454fc7#commitcomment-180899917 |
|
To clarify, it helps with the performance but doesn't actually address the original comment. The 𝒪(𝑁²) comes from the chain structure itself: child[0] chains through 𝑁-1 hops, child[1] through 𝑁-2, etc. To eliminate this, I explored a possibility in #4090 briefly but couldn't make it work correctly |
|
What you would need is a (self-balancing) tree structure, such as an AVL or Splay (not sure what the best here is - depends on usage I suppose). You need to be able to split and merge the tree (when you reassign a node in the middle) and find the right-most node starting from any node in the middle. Worst case could be O(log n) and most likely even close to O(1) if you splay correctly. I never did get it to work either though when I tried. Something about the intrusive nature of parent pointers in trees and the balancing operations needed and I didn't find an existing impl that fit to not have to invent it here. EDIT: "worst case" should probably be "amortized" in the above, a true online worst case structure would be more complicated, see e.g. Scapegoat tree or Multi-Splay tree. It really does get hairy! |
|
Actually, the current structure might not actually form a simple chain, but a tree. You can tell multiple |
…ompression # Conflicts: # packages/yew/src/dom_bundle/position.rs
This addresses a TODO left by @WorldSEnder
with_next_siblingis called on everyDomSlot::insert, which backs every DOM node insertion.For a
BListof N component children processed right-to-left, the total chain hops across allinsertions is 1 + 2 + ... + N = O(N^2). Reducing the constant factor per hop directly improves
large-list creation and reconciliation.